package mode7.ui.selectionbrowser
{
	import com.greensock.TweenLite;
	import com.greensock.easing.Quart;
	import com.lbox.util.collections.SelectionGroup;
	import com.lbox.util.interfaces.IInteractiveSelection;
	
	import flash.display.InteractiveObject;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.Event;
	
	
	/**
	 * @title 			SelectionBrowser
	 * @description 	Displays a group of IInteractiveSelections via SelectionGroup
	 * @version 		1.0
	 * @since			07/01/2010
	 * @author			James Allen | Lunchbox www.lbox.com
	 **/
	
	public class SelectionBrowser extends Sprite
	{
		
		private var _index:int = 0;
		private var _selectionMask:Shape;
		private var _selectionContainer:Sprite;
		private var _looping:Boolean = true;
		private var _selectionGroup:SelectionGroup;
		private var _page:int;
		private var _direction:int = 1;
		private var _width:Number;
		private var _height:Number;
		private var _padding:Number;
		private var _selectionWidth:Number;
		private var _selectionHeight:Number;
		private var _pageOffsetX:Number = 0;
		private var _selectionsPerPage:int = 0;
		private var _duration:Number;
		private var _ease:Function = Quart.easeOut;
		
		public function SelectionBrowser(width:Number = 200, height:Number = 50, selectionWidth:Number = 50, selectionHeight:Number = 50, padding:Number = 0, duration:Number = 1)
		{
			_width = width;
			_height = height;
			_selectionWidth = selectionWidth;
			_selectionHeight = selectionHeight;
			_padding = padding;
			_duration = duration;
			init();
		}
		
		public function selectIndex(value:int):void
		{
			if (_selectionGroup.length == 0) return;
			_selectionGroup.index = value;
		}
		
		private function init():void
		{
			_selectionGroup = new SelectionGroup();
			_selectionGroup.addEventListener(Event.CHANGE, handleSelectionChange);
			_selectionContainer = new Sprite();
			_selectionMask = new Shape();
			addChild(_selectionMask);
			addChild(_selectionContainer);
			_selectionContainer.mask = _selectionMask;
			draw();
		}
		
		public function set selectionsPerPage(value:int):void
		{
			if (value > 0)
			{
				_selectionGroup.selectionsPerPage = value;
			}
			_selectionsPerPage = value;
			formatPages();
		}
		
		public function get selectionsPerPage():int
		{
			return _selectionGroup.selectionsPerPage;
		}
		
		public function addSelection(selection:IInteractiveSelection):void
		{
			_selectionGroup.addSelection(selection);
			formatPages();
		}
		
		public function nextPage():void
		{
			if (_selectionGroup.length == 0) return;
			var pageIndex:int = _page + 1;
			if (pageIndex >= _selectionGroup.pages.length)
			{
				
				if (_looping)
				{
					pageIndex = 0;
				}
				else
				{
					pageIndex = _page;
					dispatchEvent(new Event(Event.COMPLETE));
					return;
				}
			}
			_direction = -1;
			_pageOffsetX -= (_selectionGroup.selectionsPerPage * (_selectionWidth + _padding));
			gotoPage(pageIndex);
		}
		
		public function previousPage():void
		{
			if (_selectionGroup.length == 0) return;
			var pageIndex:int = _page - 1;
			if (pageIndex < 0)
			{
				if (_looping)
				{
					pageIndex = _selectionGroup.pages.length - 1;
				}
				else
				{
					pageIndex = _page;
					dispatchEvent(new Event(Event.COMPLETE));
					return;
				}
			}
			_direction = 1;
			_pageOffsetX += (_selectionGroup.selectionsPerPage * (_selectionWidth + _padding));
			gotoPage(pageIndex);
		}
		
		public function nextSelection():void
		{
			if (_selectionGroup.length == 0) return;
			var selectionIndex:int = _index + 1;
			if (selectionIndex >= _selectionGroup.length)
			{
				
				if (_looping)
				{
					selectionIndex = selectionIndex - _selectionGroup.length;
				}
				else
				{
					selectionIndex = _index;
					dispatchEvent(new Event(Event.COMPLETE));
					return;
				}
			}
			_direction = -1;
			gotoSelection(selectionIndex);
		}
		
		public function previousSelection():void
		{
			if (_selectionGroup.length == 0) return;
			var selectionIndex:int = _index - 1;
			if (selectionIndex < 0)
			{
				if (_looping)
				{
					selectionIndex = _selectionGroup.length + selectionIndex;
				}
				else
				{
					selectionIndex = _index;
					dispatchEvent(new Event(Event.COMPLETE));
					return;
				}
			}
			_direction = 1;
			gotoSelection(selectionIndex);
		}
		
		private function handleSelectionChange(e:Event):void
		{
			_index = _selectionGroup.index;
			dispatchEvent(e);
		}
		
		private function gotoSelection(selectionIndex:int):void
		{
			if (_selectionGroup.length == 0) return;
			var offsetX:Number;
			var numDif:int = Math.abs(selectionIndex - _index);
			if (_direction == -1)
			{
				if (selectionIndex < _index)
				{
					numDif = _selectionGroup.length - _index;
					numDif += selectionIndex;
				}
			}
			else if (_direction == 1)
			{
				if (selectionIndex > _index)
				{
					numDif = _index;
					numDif += _selectionGroup.length - selectionIndex;
				}
			}
			offsetX = _direction * ((numDif) * (_selectionWidth + _padding));
			_pageOffsetX += offsetX;
			_index = selectionIndex;
			positionPages();
		}
		
		private function gotoPage(pageIndex:int):void
		{
			if (_selectionGroup.length == 0) return;
			_page = pageIndex;
			positionPages();
		}
		
		protected function positionPages():void
		{
			if (_selectionGroup.length == 0) return;
			if (!_looping)
			{
				if (_pageOffsetX < -_selectionContainer.width + _width) _pageOffsetX = -_selectionContainer.width + _width;
				if (_pageOffsetX > 0) _pageOffsetX = 0;
			}
			TweenLite.to(_selectionContainer, _duration, {x:_pageOffsetX, ease:_ease, onUpdate:updateContainer, onComplete:finishScroll});
		}
		
		private function finishScroll():void
		{
			if (!_looping)
			{
				trace("complete " + _selectionContainer.x);
				dispatchEvent(new Event(Event.COMPLETE));
				return;
			}
			var offsetX:Number = _selectionContainer.x;
			for (var i:int = 0; i < _selectionGroup.length; i ++)
			{
				var selection:InteractiveObject = IInteractiveSelection(_selectionGroup.selections[i]).io as InteractiveObject;
				selection.x += offsetX;
			}
			_selectionContainer.x = 0;
			_pageOffsetX = _selectionContainer.x;
			dispatchEvent(new Event(Event.COMPLETE));
		}
		
		private function updateContainer():void
		{
			if (!_looping)
			{
				return;
			}
			var offsetX:Number = 0;
			var containerOffset:Number = _selectionContainer.x;
			for (var i:int = 0; i< _selectionGroup.length; i ++)
			{
				var selection:InteractiveObject = IInteractiveSelection(_selectionGroup.selections[i]).io;
				offsetX =  selection.x + containerOffset;
				if (_direction == -1)
				{
					if (offsetX < -_selectionWidth)	selection.x += _selectionGroup.length * (_selectionWidth + _padding);
				}
				else
				{
					if (offsetX > _width) selection.x -= (_selectionGroup.length * (_selectionWidth + _padding));
				}
			}
			
		}
		
		private function formatPages():void
		{
			for (var i:int = _selectionContainer.numChildren - 1; i >= 0; i--)
			{
				_selectionContainer.removeChildAt(i);
			}
			var offsetX:Number = 0;
			_pageOffsetX = 0;
			_selectionContainer.x = 0;
			if (_selectionsPerPage == 0)
			{
				_selectionGroup.selectionsPerPage = Math.floor(_width/(_selectionWidth + _padding));
			}
			for (i = 0; i< _selectionGroup.length; i ++)
			{
				var selection:InteractiveObject = IInteractiveSelection(_selectionGroup.selections[i]).io;
				_selectionContainer.addChild(selection);
				selection.x = offsetX;
				positionSelection(selection);
				offsetX += _selectionWidth + _padding;
			}
		}
		
		private function draw():void
		{
			_selectionMask.graphics.clear();
			_selectionMask.graphics.beginFill(0x000000);
			_selectionMask.graphics.drawRect(0, 0, _width, _height);
			_selectionMask.graphics.endFill();
			
		}
		
		private function destroySelectionGroup():void
		{
			if (_selectionGroup == null) return;
			for (var i:int = _selectionContainer.numChildren - 1; i >= 0; i --)
			{
				_selectionContainer.removeChildAt(i);
			}
			
		}
		
		private function positionSelection(selection:InteractiveObject):void
		{
			
			showSelection(selection);
		}
		
		protected function showSelection(selection:InteractiveObject):void
		{
			selection.visible = true;
			selection.alpha = 1;
		}
		
		public function getPageIndexOfSelection(selection:IInteractiveSelection):int
		{
			return _selectionGroup.getPageIndexOfSelection(selection);
		}

		public override function get width():Number
		{
			return _width;
		}

		public override function set width(value:Number):void
		{
			if (_width != value)
			{
				_width = value;
				draw();
				formatPages();
			}
		}

		public override function get height():Number
		{
			return _height;
		}

		public override function set height(value:Number):void
		{
			if (_height != value)
			{
				_height = value;
				draw();
				formatPages();
			}
		}

		public function get padding():Number
		{
			return _padding;
		}

		public function set padding(value:Number):void
		{
			if (_padding != value)
			{
				_padding = value;
				formatPages();
			}
		}

		public function get selectionWidth():Number
		{
			return _selectionWidth;
		}

		public function set selectionWidth(value:Number):void
		{
			if (_selectionWidth != value)
			{
				_selectionWidth = value;
				formatPages();
			}
		}

		public function get selectionHeight():Number
		{
			return _selectionHeight;
		}

		public function set selectionHeight(value:Number):void
		{
			if (_selectionHeight != value)
			{
				_selectionHeight = value;
				formatPages();
			}
		}

		public function get direction():int
		{
			return _direction;
		}

		public function set direction(value:int):void
		{
			_direction = value;
			if (_direction > 1 || _direction == 0) _direction = 1;
			if (_direction < -1) _direction = -1;
		}

		public function get page():int
		{
			return _page;
		}

		public function set page(value:int):void
		{
			_page = value;
			gotoPage(_page);
		}
		
		public function get totalPages():int
		{
			return _selectionGroup.totalPages;
		}
		
		public function get totalSelections():int
		{
			return _selectionGroup.length;
		}
		
		public function get selections():Array
		{
			return _selectionGroup.selections;
		}

		public function get index():int
		{
			return _index;
		}

		public function setSelectionGroup(selectionGroup:SelectionGroup):void
		{
			destroySelectionGroup();
			_selectionGroup = selectionGroup;
			formatPages();
		}

		public function get looping():Boolean
		{
			return _looping;
		}

		public function set looping(value:Boolean):void
		{
			_looping = value;
		}

		public function get duration():Number
		{
			return _duration;
		}

		public function set duration(value:Number):void
		{
			_duration = value;
		}

		public function get ease():Function
		{
			return _ease;
		}

		public function set ease(value:Function):void
		{
			_ease = value;
		}


	}
}